
#include "DLitMatTexEffect.h"
#include "Wm5LightDirPerPixEffect.h"
#include "OBJtoTriMesh.h"
#include "ObjLoader.h"

using namespace Wm5;

OBJtoTriMesh::OBJtoTriMesh() {
}

OBJtoTriMesh::~OBJtoTriMesh() {
}

TriMesh* OBJtoTriMesh::CreateMesh(std::string path, std::string objFilename, std::string wmtfFilename)
{
	ObjLoader *loader = new0 ObjLoader(path, objFilename);
	
	VertexFormat* vformat = VertexFormat::Create(3,
												 VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
												 VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0,
												 VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
    int vstride = vformat->GetStride();
	
	int numVertices = 0;
	
	std::vector<ObjLoader::Float3> positions;
	std::vector<ObjLoader::Float3> normals;
	std::vector<ObjLoader::Float2> texcoords;
	std::vector<int> indices;
	for(int i = 0; i < loader->GetGroups().size(); i++)
	{
		//int i = 0;
		for(int j = 0; j < loader->GetGroups().at(i).Meshes.size(); j++)
		{
			for(int k = 0; k < loader->GetGroups().at(i).Meshes.at(j).Faces.size(); k++)
			{
				if(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.size() > 3)
				{
					int n = loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.size();
					for(int l = 0; l < (n-2); l++)
					{
						//Insert Vertex 1
						ObjLoader::Float3 pos = loader->GetPositions().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(0).PosIndex);
						ObjLoader::Float3 norm = loader->GetNormals().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(0).NorIndex);
						ObjLoader::Float2 texc = loader->GetTCoords().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(0).TcdIndex);
						positions.push_back(pos);
						normals.push_back(norm);
						texcoords.push_back(texc);
						indices.push_back(numVertices);
						numVertices++;
						
						//Insert Vertex l+1
						pos = loader->GetPositions().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(l+1).PosIndex);
						norm = loader->GetNormals().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(l+1).NorIndex);
						texc = loader->GetTCoords().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(l+1).TcdIndex);
						positions.push_back(pos);
						normals.push_back(norm);
						texcoords.push_back(texc);
						indices.push_back(numVertices);
						numVertices++;
						
						//Insert Vertex l+2
						pos = loader->GetPositions().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(l+2).PosIndex);
						norm = loader->GetNormals().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(l+2).NorIndex);
						texc = loader->GetTCoords().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(l+2).TcdIndex);
						positions.push_back(pos);
						normals.push_back(norm);
						texcoords.push_back(texc);
						indices.push_back(numVertices);
						numVertices++;
					}
				}	
				else
				{
					for(int l = 0; l < 3; l++)
					{
						ObjLoader::Float3 pos = loader->GetPositions().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(l).PosIndex);
						ObjLoader::Float3 norm = loader->GetNormals().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(l).NorIndex);
						ObjLoader::Float2 texc = loader->GetTCoords().at(loader->GetGroups().at(i).Meshes.at(j).Faces.at(k).Vertices.at(l).TcdIndex);
						positions.push_back(pos);
						normals.push_back(norm);
						texcoords.push_back(texc);
						indices.push_back(numVertices);
						numVertices++;
					}
				}
			}
		}
	}
	Wm5::Float3 *poss = (Wm5::Float3 *)malloc(sizeof(Wm5::Float3)*positions.size());
	Wm5::Float3 *norms = (Wm5::Float3 *)malloc(sizeof(Wm5::Float3)*positions.size());
	Wm5::Float2 *tcords = (Wm5::Float2 *)malloc(sizeof(Wm5::Float2)*positions.size());
	
	for(int i = 0; i < positions.size(); i++)
	{
		poss[i] = Float3(positions[i].x, positions[i].y, positions[i].z);
		norms[i] = Float3(normals[i].x, normals[i].y, normals[i].z);
		tcords[i] = Float2(texcoords[i].x, texcoords[i].y);
	}
	
	IndexBuffer *ibuffer = new0 IndexBuffer((int)indices.size(), sizeof(int));
	VertexBuffer *vbuffer = new0 VertexBuffer((int)indices.size(), vstride);
	VertexBufferAccessor vba(vformat, vbuffer);
	//vector<int> iit = indices.begin();
	
	int *ind = (int *)malloc(sizeof(int)*positions.size());
	for(int i = 0; i<positions.size(); i++)
	{
		vba.Position<Wm5::Float3>(i) = poss[i];
		vba.Normal<Wm5::Float3>(i) = norms[i];
		vba.TCoord<Wm5::Float2>(0, i) = tcords[i];
		
		ind[i] = i;
		int a = ind[i];
	}
	
	memcpy(ibuffer->GetData(), &ind[0], positions.size()*sizeof(int));
	TriMesh* mesh = new0 TriMesh(vformat, vbuffer, ibuffer);
	
	std::string baseName = Environment::GetPathR(wmtfFilename);
    Texture2D* baseTexture = Texture2D::LoadWMTF(baseName);
    baseTexture->GenerateMipmaps();
	
	
	VisualEffectInstance* instance = Texture2DEffect::CreateUniqueInstance(
																		   baseTexture, Shader::SF_LINEAR_LINEAR, Shader::SC_REPEAT,
																		   Shader::SC_REPEAT);	
	 
	
	
    std::string effectFile = Environment::GetPathR("DLitMatTex.wmfx");
	DLitMatTexEffect* effect = new0 DLitMatTexEffect(effectFile);
	
	
	//	DLitMatTexEffect* effect = new0 DLitMatTexEffect("shaders/DLitMatTex.wmfx");
   	
	LightPtr light = new0 Light(Light::LT_DIRECTIONAL);
	light->Ambient = Float4(1.0f, 1.0f, 1.0f, 1.0f);
    light->Diffuse = Float4(1.0f, 1.0f, 1.0f, 1.0f);
    light->Specular = Float4(1.0f, 1.0f, 1.0f, 1.0f);
    light->SetDirection(AVector(-1.0f, -1.0f, -1.0f));
	
	Wm5::Material *mat = new0 Wm5::Material();
	//Material* copper = new0 Material();
    mat->Emissive = Float4(0.0f, 0.0f, 0.0f, 1.0f);
    mat->Ambient = Float4(0.0575f, 0.0575f, 0.0575f, 1.0f);
    mat->Diffuse = Float4(0.066f, 0.066f, 0.066f, 1.0f);
    mat->Specular = Float4(0.580594f, 0.580594f, 0.580594f, 51.2f);
	
	//mesh->SetEffectInstance(effect->CreateInstance(light, mat, baseTexture));
	mesh->SetEffectInstance(instance);
	
	return mesh;
}